package com.guigu.auth.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.guigu.auth.entity.AuthResource;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guigu.auth.entity.AuthRoleAuthority;
import com.guigu.auth.entity.AuthUser;
import com.guigu.auth.entity.AuthUserRole;
import com.guigu.auth.mapper.AuthResourceMapper;
import com.guigu.auth.service.AuthResourceService;
import com.guigu.auth.service.AuthRoleAuthorityService;
import com.guigu.auth.service.AuthUserRoleService;
import com.guigu.auth.service.AuthUserService;
import com.guigu.tms.result.R;
import com.guigu.tms.result.ResultCode;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源 服务实现类
 * </p>
 *
 * @author TaoLong
 * @since 2021-12-06
 */
@Service
@CacheConfig(cacheNames = "authResource")
public class AuthResourceServiceImpl extends ServiceImpl<AuthResourceMapper, AuthResource> implements AuthResourceService {

    @Autowired
    private AuthUserService authUserService;

    @Autowired
    private AuthUserRoleService authUserRoleService;

    @Autowired
    private AuthRoleAuthorityService authRoleAuthorityService;

    @Override
    @Cacheable(key = "#userId")
    public R<Set<AuthResource>> queryResourcesBasedOnUserId(String userId) {
        /**
         * 根据用户Id查询岗位Id
         */
        AuthUser user = authUserService.getById(userId);
        if (ObjectUtils.isEmpty(user)) {
            return new R<>(ResultCode.SUCCESS_CODE, null);
        }
        /**
         * 根据岗位查询角色Id集合
         */
        QueryWrapper<AuthUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", user.getStationId());
        List<AuthUserRole> authUserRoles = authUserRoleService.list(queryWrapper);
        if (CollUtil.isEmpty(authUserRoles)) {
            return new R<>(ResultCode.SUCCESS_CODE, null);
        }
        /**
         * 根据角色Id集合查询对应的菜单Id
         */
        Set<Long> menuIds = new HashSet<>();
        authUserRoles.stream().filter(a -> null != a.getRoleId()).forEach(authUserRole -> {
            List<Long> list = queryMenuIdsBasedOnRoleId(authUserRole.getRoleId());
            if (CollUtil.isNotEmpty(list)) {
                menuIds.addAll(list);
            }
        });
        if (CollUtil.isEmpty(menuIds)) {
            return new R<>(ResultCode.SUCCESS_CODE, null);
        }
        /**
         * 根据获取的菜单Id来获取权限信息
         */
        QueryWrapper<AuthResource> q = new QueryWrapper<>();
        q.in("menu_id", menuIds);
        List<AuthResource> resourceList = this.list(q);
        if (CollUtil.isEmpty(resourceList)) {
            return new R<>(ResultCode.SUCCESS_CODE, null);
        }
        Set<AuthResource> authResourceSet = new HashSet<>();
        authResourceSet.addAll(resourceList);
        return new R<>(ResultCode.SUCCESS_CODE, authResourceSet);
    }


    /**
     * 根据角色Id返回菜单Id
     *
     * @param roleId 角色Id
     * @return
     */
    private List<Long> queryMenuIdsBasedOnRoleId(Long roleId) {
        if (null == roleId) {
            return null;
        }
        QueryWrapper<AuthRoleAuthority> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);
        queryWrapper.select("authority_id");
        List<AuthRoleAuthority> authorityList = authRoleAuthorityService.list(queryWrapper);
        if (CollUtil.isEmpty(authorityList)) {
            return null;
        }
        List<Long> list = authorityList.stream().map(authRoleAuthority -> authRoleAuthority.getAuthorityId()).collect(Collectors.toList());
        return list;
    }

    /**
     * 查询全部权限信息
     *
     * @return
     */
    @Cacheable
    @Override
    public R<List<AuthResource>> queryAll() {
        return new R<>(ResultCode.SUCCESS_CODE, list(null));
    }
}
